namespace SubhadraSolutions.Sharp.Logging.LogPublishers
{
    using SubhadraSolutions.Sharp.Logging.Common;
    using SubhadraSolutions.Sharp.Logging.Contracts;
    using SubhadraSolutions.Sharp.Utils.Collections.Concurrent;
    using SubhadraSolutions.Sharp.Utils.Contracts;
    using System;
    using System.Collections.Generic;

    public abstract class AbstractBufferedLogPublisher : AbstractLogPublisher, IInitializable
    {
        #region Constructors

        ~AbstractBufferedLogPublisher()
        {
            Dispose(false);
        }

        #endregion Constructors

        #region Properties

        public IComparer<LogStoreItem> Comparer
        {
            get;
            set;
        }

        public bool IsInitialized
        {
            get;
            private set;
        }

        public ILogBuffer LogStore
        {
            get;
            set;
        }

        #endregion Properties

        #region Methods

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public void Initialize()
        {
            if (!IsInitialized)
            {
                initializeProtected();
                if (LogStore == null)
                {
                    LogStore = getLogStore();
                }
                var initializable = LogStore as IInitializable;
                if (initializable != null && !initializable.IsInitialized)
                {
                    initializable.Initialize();
                }
                LogStore.OnStoreFlush += LogStore_OnStoreFlush;
                IsInitialized = true;
            }
        }

        protected virtual void Dispose(bool disposing)
        {
            LogStore.Dispose();
            LogStore.OnStoreFlush -= LogStore_OnStoreFlush;
        }

        protected virtual ILogBuffer getLogStore()
        {
            var store = new LogBuffer { BufferSize = (85000 - (IntPtr.Size * 5)) / IntPtr.Size };
            return store;
        }

        protected virtual void initializeProtected()
        {
        }

        private void LogStore_OnStoreFlush(object sender, StoreFlushEventArgs<LogStoreItem> e)
        {
            if (Comparer != null)
            {
                e.Sort(Comparer);
            }
            raiseOnFlushEvent(e);
        }

        #endregion Methods
    }
}